
package com.smartfit;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;

import android.util.Xml;

import com.dtw.TimeWarpInfo;
import com.timeseries.TimeSeries;
import com.util.DistanceFunction;
import com.util.DistanceFunctionFactory;

public class Examplar
{
	// parent
	ExamplarDB m_ExamplarDB;
	// ID
	private int m_iID = -1;
	// description
	private String m_strDescription;
	// icon
	private String m_strIcon;
	
	//
	//
	//
	
	private final static Comparator<Double> SORT_DOUBLE = new Comparator<Double>()
	{
		@Override
		public int compare( Double arg0 , Double arg1 )
		{
			// TODO Auto-generated method stub
			return Double.compare( arg0 , arg1 );
		}
	};
	
	//
	// Config 파일 정보
	//
	
	// 대표파일 갯수
	private int m_iNumExamplarFiles = 0;
	// examplar files
	private ArrayList<String> m_ExamplarFiles = new ArrayList<String>();
	// 샘플파일 갯수
	private int m_iNumSampleFiles = 0;
	// sample files
	private ArrayList<String> m_SampleFiles = new ArrayList<String>();
	
	// 대표 config 파일 태그
	final private String EXAMPLAR_CONFIG_FILE_TAG = "ExamplarCfg"; 
	// 대표파일  태그
	final private String EXAMPLAR_FILE_TAG = "Examplar"; 
	// 샘플 config 파일 태그
	final private String SAMPLE_CONFIG_FILE_TAG = "SampleCfg"; 
	// 샘플파일 태그
	final private String SAMPLE_FILE_TAG = "Sample"; 

	// 파일 갯수 태그
	final private String NUM_FILE_TAG = "NumFiles"; 
	// 파일 이름 태그
	final private String FILE_NAME_TAG = "FileName";
	
	//
	// 가속도 데이터
	//

	// 대표값
	private ArrayList<AccelValueFileData> m_Examplars = new ArrayList<AccelValueFileData>();
	
	// 파일 확장자
	final private String ACCEL_VALUE_FILE_EXT = "xml";
	
	//
	// 샘플라일 정보
	//
	
	// 샘플파일  태그
	final private String EXAMPLAR_SAMPLE_FILE_TAG = "ExamplarSample";
	// 샘플데이터 시간간격
	final private String EXAMPLAR_SAMPLE_DATA_GRAVITY_TAG = "SampleGravity";	
	// 샘플데이터 시간간격
	final private String EXAMPLAR_SAMPLE_DATA_INTERVAL_TAG = "SampleInterval";	
	// 샘플 거리 데이터
	final private String EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG = "SampleDistanceData";	
	// 샘플 각도 데이터
	final private String EXAMPLAR_SAMPLE_ANGLE_DATA_TAG = "SampleAngleData";	
	// 샘플데이터 X
	final private String EXAMPLAR_SAMPLE_DATA_X_TAG = "X";
	// 샘플데이터 Y
	final private String EXAMPLAR_SAMPLE_DATA_Y_TAG = "Y";
	// 샘플데이터 Z
	final private String EXAMPLAR_SAMPLE_DATA_Z_TAG = "Z";

	// X
	public ArrayList<Double> m_ExamplarAccelValueX = new ArrayList<Double>();
	// Y
	public ArrayList<Double> m_ExamplarAccelValueY = new ArrayList<Double>();
	// Z
	public ArrayList<Double> m_ExamplarAccelValueZ = new ArrayList<Double>();
	
	public Examplar( ExamplarDB db , int iID )
	{
		m_ExamplarDB = db;
		m_iID = iID;
		m_strDescription = "";
		m_strIcon = "";
	}
	
	public int GetID()
	{
		return m_iID;
	}
	
	public void SetDescription( String strDescription )
	{
		m_strDescription = strDescription;
	}
	
	public String GetDescription()
	{
		return m_strDescription;
	}
	
	public void SetIcon( String strIcon )
	{
		m_strIcon = strIcon;
	}
	
	public String GetIcon()
	{
		return m_strIcon;
	}
	
	protected boolean WriteConfigFile( String strDataPath )
	{
		try
		{
			File file = new File( strDataPath );
			if ( !file.exists() )
			{
				file.mkdirs();
			}
			
			file = new File( strDataPath + "/" + String.valueOf( m_iID ) + ".xml" );
			
			if ( !file.exists() )
			{
				file.createNewFile();
			}
			
			FileOutputStream fos = new FileOutputStream( file );
			XmlSerializer serializer = Xml.newSerializer();
			
            //we set the FileOutputStream as output for the serializer, using UTF-8 encoding
            serializer.setOutput( fos , "UTF-8" );
            
            //Write <?xml declaration with encoding (if encoding not null) and standalone flag (if standalone not null)
            serializer.startDocument( null , Boolean.valueOf( true ) );
            //set indentation option
            serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output" , true );
            
            {
            	{
	            	serializer.startTag( null , EXAMPLAR_CONFIG_FILE_TAG );
	            	
            		// 대표파일 갯수
            		serializer.attribute( null , NUM_FILE_TAG , String.valueOf( m_iNumExamplarFiles ) );
            		
            		for ( int i = 0 ; i < m_iNumExamplarFiles ; i++ )
            		{
            			serializer.startTag( null , EXAMPLAR_FILE_TAG );
            			serializer.attribute( null , FILE_NAME_TAG , m_ExamplarFiles.get( i ) );
            			serializer.endTag( null , EXAMPLAR_FILE_TAG );
            		}
	            	
	            	serializer.endTag( null , EXAMPLAR_CONFIG_FILE_TAG );
            	}

            	{
            		serializer.startTag( null , SAMPLE_CONFIG_FILE_TAG );
            	
            		// 샘플파일 갯수
            		serializer.attribute( null , NUM_FILE_TAG , String.valueOf( m_iNumSampleFiles ) );
            		
            		for ( int i = 0 ; i < m_iNumSampleFiles ; i++ )
            		{
            			serializer.startTag( null , SAMPLE_FILE_TAG );
            			serializer.attribute( null , FILE_NAME_TAG , m_SampleFiles.get( i ) );
            			serializer.endTag( null , SAMPLE_FILE_TAG );
            		}
            	
            		serializer.endTag( null , SAMPLE_CONFIG_FILE_TAG );
            	}
            }
            
            serializer.endDocument();
            //write xml data into the FileOutputStream
            serializer.flush();
            
            //finally we close the file stream
            fos.close();
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}
	
	protected boolean LoadConfigFile( String strDataPath )
	{
		try
		{
			// 파일 패스 체크
			File file = new File( strDataPath );
			if ( !file.exists() )
			{
				file.mkdirs();
			}
			
			file = new File( strDataPath + "/" + String.valueOf( m_iID ) + ".xml" );
			
			if ( !file.exists() )
			{
				file.createNewFile();

				return WriteConfigFile( strDataPath );				
			}
			
			FileInputStream fis = new FileInputStream ( file );

	        //XmlPullParser를 사용하기 위해서 생성합니다.
	        XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 
	        XmlPullParser parser = factory.newPullParser();
	        
            //we set the FileInputStream as input for the XmlPullParser, using UTF-8 encoding
	        parser.setInput( fis , "UTF-8" );
	        
	        int parserEvent = parser.getEventType();
	        
	        while ( parserEvent != XmlPullParser.END_DOCUMENT )
	        {
	        	switch ( parserEvent )
	        	{
	        		case XmlPullParser.START_TAG:
	        			
	        			String strTagName = parser.getName();
	        			
	        			if ( strTagName.equals( EXAMPLAR_CONFIG_FILE_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( NUM_FILE_TAG ) )
	        					{
	        						String strNumExamplarFiles = parser.getAttributeValue( i );
	        						m_iNumExamplarFiles = Integer.valueOf( strNumExamplarFiles );
	        					}
	        				}
	        			}
	        			else if ( strTagName.equals( EXAMPLAR_FILE_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( FILE_NAME_TAG ) )
	        					{
	        						String strExamplarFileName = parser.getAttributeValue( i );
	        						m_ExamplarFiles.add( strExamplarFileName );
	        					}
	        				}
	        			}
	        			else if ( strTagName.equals( SAMPLE_CONFIG_FILE_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( NUM_FILE_TAG ) )
	        					{
	        						String strNumSampleFiles = parser.getAttributeValue( i );
	        						m_iNumSampleFiles = Integer.valueOf( strNumSampleFiles );
	        					}
	        				}
	        			}
	        			else if ( strTagName.equals( SAMPLE_FILE_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( FILE_NAME_TAG ) )
	        					{
	        						String strSampleFileName = parser.getAttributeValue( i );
	        						m_SampleFiles.add( strSampleFileName );
	        					}
	        				}
	        			}
	        			else
	        			{
	        			}
	        			
	        			break;

	        		case XmlPullParser.END_TAG:
	        			
	        			break;
	        			
	        		case XmlPullParser.TEXT:
	        			
	        			break;
	        	}
	        	
	        	parserEvent = parser.next();
	        }
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}

	protected void WriteSampleFile( String strDataPath , AccelValueFileData data )
	{
		try
		{
			String strFileName = String.valueOf( m_iID ) + "_" + String.valueOf( m_iNumSampleFiles ) + "." + ACCEL_VALUE_FILE_EXT;
			
			if ( WriteAccelValueFileWithXML( strDataPath , strFileName , data ) )
			{
				// 파일 저장 성공 처리
				m_iNumSampleFiles++;
				m_SampleFiles.add( strFileName );
				
				// config 파일 업데이트
				WriteConfigFile( strDataPath );
			}
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}
	
	protected boolean LoadSampleFile( String strDataPath , String strFileName , AccelValueFileData data )
	{
		try
		{
			if ( LoadAccelValueFileWithXML( strDataPath , strFileName , data ) )
			{
				return true;
			}

		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return false;
	}

	protected boolean LoadExamplarFile( String strDataPath )
	{
		try
		{
			for ( int i = 0 ; i < m_iNumExamplarFiles ; i++ )
			{
				AccelValueFileData s = new AccelValueFileData();
				
				if ( LoadAccelValueFileWithXML( strDataPath , m_ExamplarFiles.get( i ) , s ) )
				{
					m_Examplars.add( s );
				}
			}
			
			return true;
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
		
		return false;
	}
	
	protected boolean IsLoadedExamplar()
	{
		if ( m_Examplars.isEmpty() )
		{
			return false;
		}
		
		return true;
	}

	protected boolean GenerateExamplar( String strDataPath , int iNumMaxExamplars )
	{
		if ( m_SampleFiles.size() != m_iNumSampleFiles )
		{
			
		}
		
		// 데이터 공간 확보

		AccelValueFileData data[] = new AccelValueFileData[m_iNumSampleFiles];
		
		for ( int i = 0 ; i < m_iNumSampleFiles ; i++ )
		{
			data[i] = new AccelValueFileData();
		}
		
		// 파일 로딩 및 데이터 채우기
		
		for ( int i = 0 ; i < m_iNumSampleFiles ; i++ )
		{
			LoadSampleFile( strDataPath , m_SampleFiles.get( i ) , data[i] );
		}
		
		// 계산
		
		ArrayList<Double> result = new ArrayList<Double>();
		
		for ( int iCurrSample = 0 ; iCurrSample < m_iNumSampleFiles ; iCurrSample++ )
		{
			AccelValueFileData currSample = data[iCurrSample];
			
			double x;
			double y;
			double z;
			
			double sum = 0;
			
			for ( int i = 0 ; i < m_iNumSampleFiles ; i++ )
			{
				AccelValueFileData cmpSample = data[i];
				
				x = GetWarpInfo( currSample.m_Angle.accelValueXs , cmpSample.m_Angle.accelValueXs );
				y = GetWarpInfo( currSample.m_Angle.accelValueYs , cmpSample.m_Angle.accelValueYs );
				z = GetWarpInfo( currSample.m_Angle.accelValueZs , cmpSample.m_Angle.accelValueZs );
				
				sum += Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
			}
			
			result.add( sum );
		}
		
		// 결과
		Collections.sort( result , SORT_DOUBLE );
		// 결과 저장
		int iNumExamplars = ( result.size() > iNumMaxExamplars ) ? iNumMaxExamplars : result.size();
		
		// 이전 대표값 삭제
		m_iNumExamplarFiles = 0;
		m_ExamplarFiles.clear();
		m_Examplars.clear();
		
		for ( int i = 0 ; i < iNumExamplars ; i++ )
		{
			String strFileName = "p_" + String.valueOf( m_iID ) + "_" + String.valueOf( i ) + "." + ACCEL_VALUE_FILE_EXT;

			if ( WriteAccelValueFileWithXML( strDataPath , strFileName , data[i] ) )
			{
				m_iNumExamplarFiles++;
				m_ExamplarFiles.add( strFileName );
				
				// 대표값 저장
				AccelValueFileData s = new AccelValueFileData();
				s.Copy( data[i] );
				
				m_Examplars.add( s );
			}
		}
		
		// config 파일 업데이트
		m_iNumExamplarFiles = iNumExamplars;
		WriteConfigFile( strDataPath );

		return true;
	}

	protected boolean WriteAccelValueFileWithXML( String strDataPath , String strFileName , AccelValueFileData data )
	{
		try
		{
			File file = new File( strDataPath );
			if ( !file.exists() )
			{
				file.mkdirs();
			}
			
			file = new File( strDataPath + "/" + strFileName );
			
			if ( !file.exists() )
			{
				file.createNewFile();
			}
			
			FileOutputStream fos = new FileOutputStream( file );
			XmlSerializer serializer = Xml.newSerializer();
			
            //we set the FileOutputStream as output for the serializer, using UTF-8 encoding
            serializer.setOutput( fos , "UTF-8" );
            
            //Write <?xml declaration with encoding (if encoding not null) and standalone flag (if standalone not null)
            serializer.startDocument( null , Boolean.valueOf( true ) );
            //set indentation option
            serializer.setFeature( "http://xmlpull.org/v1/doc/features.html#indent-output" , true );
            
        	{
            	serializer.startTag( null , EXAMPLAR_SAMPLE_FILE_TAG );
            	
            	// 샘플데이터 시간간격
            	serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_GRAVITY_TAG , ( data.IsContainedGravity() ? "true" : "false" ) );
        		// 샘플데이터 시간간격
        		serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_INTERVAL_TAG , String.valueOf( data.GetTimeInterval() ) );
        		/*
        		{
        			Axis3f sumDistance = data.GetDistance();
	        		// 샘플데이터 거리
	        		serializer.startTag( null , EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG );
	        		
					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_X_TAG , String.valueOf( sumDistance.x ) );
					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Y_TAG , String.valueOf( sumDistance.y ) );
					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Z_TAG , String.valueOf( sumDistance.z ) );

					serializer.endTag( null , EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG );
        		}
        		*/

        		{
	    			int iNumAccelValue = data.GetNumData( AccelValueFileData.DATA_TYPE_ANGLE );
	    			
	    			for ( int i = 0 ; i < iNumAccelValue ; i++ )
	    			{
	    				serializer.startTag( null , EXAMPLAR_SAMPLE_ANGLE_DATA_TAG );
	    				
	    				{
	    					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_X_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_ANGLE , AccelValueFileData.DATA_X , i ) ) );
	    					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Y_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_ANGLE , AccelValueFileData.DATA_Y , i ) ) );
	    					serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Z_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_ANGLE , AccelValueFileData.DATA_Z , i ) ) );
	    				}
	    				
	    				serializer.endTag( null , EXAMPLAR_SAMPLE_ANGLE_DATA_TAG );
	    			}
        		}
        		
        		{
        			int iNumDistanceValue = data.GetNumData( AccelValueFileData.DATA_TYPE_DISTANCE );
        			
	    			for ( int i = 0 ; i < iNumDistanceValue ; i++ )
	        		{
		        		// 샘플데이터 거리
		        		serializer.startTag( null , EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG );
		        		
		        		{
							serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_X_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_DISTANCE , AccelValueFileData.DATA_X , i ) ) );
							serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Y_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_DISTANCE , AccelValueFileData.DATA_Y , i ) ) );
							serializer.attribute( null , EXAMPLAR_SAMPLE_DATA_Z_TAG , String.valueOf( data.Get( AccelValueFileData.DATA_TYPE_DISTANCE , AccelValueFileData.DATA_Z , i ) ) );
		        		}
	
						serializer.endTag( null , EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG );
	        		}
        		}
        		
        		serializer.endTag( null , EXAMPLAR_SAMPLE_FILE_TAG );
        	}
            
            serializer.endDocument();
            //write xml data into the FileOutputStream
            serializer.flush();
            
            //finally we close the file stream
            fos.close();
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}

	protected boolean LoadAccelValueFileWithXML( String strDataPath , String strFileName , AccelValueFileData data )
	{
		try
		{
			// 파일 패스 체크
			File file = new File( strDataPath );
			if ( !file.exists() )
			{
				return false;
			}
			
			file = new File( strDataPath + "/" + strFileName );
			
			if ( !file.exists() )
			{
				return false;
			}
			
			FileInputStream fis = new FileInputStream ( file );

	        //XmlPullParser를 사용하기 위해서 생성합니다.
	        XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 
	        XmlPullParser parser = factory.newPullParser();
	        
            //we set the FileInputStream as input for the XmlPullParser, using UTF-8 encoding
	        parser.setInput( fis , "UTF-8" );
	        
	        int parserEvent = parser.getEventType();
	        
	        while ( parserEvent != XmlPullParser.END_DOCUMENT )
	        {
	        	switch ( parserEvent )
	        	{
	        		case XmlPullParser.START_TAG:
	        			
	        			String strTagName = parser.getName();
	        			
	        			if ( strTagName.equals( EXAMPLAR_SAMPLE_FILE_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        	            	// 샘플데이터 시간간격
	        					if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_INTERVAL_TAG ) )
	        					{
	        						String strTimeInterval = parser.getAttributeValue( i );
	        						data.m_iTimeInterval = Integer.valueOf( strTimeInterval );
	        					}
	        					else if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_GRAVITY_TAG ) )
	        					{
	        						String strGravity = parser.getAttributeValue( i );
	        						data.m_bIsContainedGravity = ( strGravity == "true" ) ? true : false;
	        					}
	        				}
	        			}
	        			else if ( strTagName.equals( EXAMPLAR_SAMPLE_ANGLE_DATA_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				if ( iNumAttributes != 3 )
	        				{
	        					throw new Exception();
	        				}	
	        				
	        				double x = 0.0;
	        				double y = 0.0;
	        				double z = 0.0;
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_X_TAG ) )
	        					{
	        						String strAccelValueX = parser.getAttributeValue( i );
	        						x = Double.valueOf( strAccelValueX );
	        					}
	        					else if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_Y_TAG ) )
	        					{
	        						String strAccelValueY = parser.getAttributeValue( i );
	        						y = Double.valueOf( strAccelValueY );
	        					}
	        					else if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_Z_TAG ) )
	        					{
	        						String strAccelValueZ = parser.getAttributeValue( i );
	        						z = Double.valueOf( strAccelValueZ );
	        					}
	        					else
	        					{
	        						throw new Exception();
	        					}
	        				}
	        				
	        				data.Set( AccelValueFileData.DATA_TYPE_ANGLE , x , y , z );
	        			}
	        			else if ( strTagName.equals( EXAMPLAR_SAMPLE_DISTANCE_DATA_TAG ) )
	        			{
	        				int iNumAttributes = parser.getAttributeCount();
	        				
	        				if ( iNumAttributes != 3 )
	        				{
	        					throw new Exception();
	        				}	
	        				
	        				double x = 0.0;
	        				double y = 0.0;
	        				double z = 0.0;
	        				
	        				for ( int i = 0 ; i < iNumAttributes ; i++ )
	        				{
	        					String strAttributeName = parser.getAttributeName( i );
	        					
	        					if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_X_TAG ) )
	        					{
	        						String strAccelValueX = parser.getAttributeValue( i );
	        						x = Double.valueOf( strAccelValueX );
	        					}
	        					else if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_Y_TAG ) )
	        					{
	        						String strAccelValueY = parser.getAttributeValue( i );
	        						y = Double.valueOf( strAccelValueY );
	        					}
	        					else if ( strAttributeName.equals( EXAMPLAR_SAMPLE_DATA_Z_TAG ) )
	        					{
	        						String strAccelValueZ = parser.getAttributeValue( i );
	        						z = Double.valueOf( strAccelValueZ );
	        					}
	        					else
	        					{
	        						throw new Exception();
	        					}
	        				}
	        				
	        				data.Set( AccelValueFileData.DATA_TYPE_DISTANCE , x , y , z );
	        				//data.SetDistance( x , y , z );
	        			}
	        			else
	        			{
	        			}
	        			
	        			break;

	        		case XmlPullParser.END_TAG:
	        			
	        			break;
	        			
	        		case XmlPullParser.TEXT:
	        			
	        			break;
	        	}
	        	
	        	parserEvent = parser.next();
	        }
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}
	/*
	protected boolean WriteAccelValueFile( String strDataPath , String strFileName , ArrayList<Double> xs , ArrayList<Double> ys , ArrayList<Double> zs )
	{
		try
		{
			File file = new File( strDataPath );
			if ( !file.exists() )
			{
				file.mkdirs();
			}
			
			file = new File( strDataPath + "/" + strFileName );
			
			if ( !file.exists() )
			{
				file.createNewFile();
			}
			
			FileOutputStream fos = new FileOutputStream( file );
			DataOutputStream dataStream = new DataOutputStream( fos );
			
			int iNumAccelValue = xs.size();
			
			for ( int i = 0 ; i < iNumAccelValue ; i++ )
			{
				dataStream.writeDouble( xs.get( i ) );
				dataStream.writeDouble( ys.get( i ) );
				dataStream.writeDouble( zs.get( i ) );
			}
			
			dataStream.close();
		}
		catch ( Exception e )
		{
			e.printStackTrace();
			
			return false;
		}
		
		return true;
	}

	public double Compare( ArrayList<Double> xs , ArrayList<Double> ys , ArrayList<Double> zs )
	{
		double fDistancce = Double.MAX_VALUE;
		
		for ( int i = 0 ; i < m_iNumExamplarFiles ; i++ )
		{
			AccelValueFileData examplar = m_Examplars.get( i );
			
			double x = GetWarpInfo( examplar.m_Angle.accelValueXs , xs );
			double y = GetWarpInfo( examplar.m_Angle.accelValueYs , ys );
			double z = GetWarpInfo( examplar.m_Angle.accelValueZs , zs );
			
			double s = Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) );

			if ( fDistancce > s )
			{
				fDistancce = s;
			}
		}
		
		return fDistancce;
	}

	public double Compare( AccelValueFileData data , CompareHistory h )
	{
		double fDistancce = Double.MAX_VALUE;
		
		int iDistanceThreshold = m_ExamplarDB.GetDistanceThreshold();
		
		Axis3f currDataDistance = data.GetDistance();
		
		Axis3f MAX_THRESHOLD = new Axis3f();
		
		MAX_THRESHOLD.x = currDataDistance.x + iDistanceThreshold;
		MAX_THRESHOLD.y = currDataDistance.y + iDistanceThreshold;
		MAX_THRESHOLD.z = currDataDistance.z + iDistanceThreshold;
		
		Axis3f MIN_THRESHOLD = new Axis3f();
		
		MIN_THRESHOLD.x = currDataDistance.x - iDistanceThreshold;
		MIN_THRESHOLD.y = currDataDistance.y - iDistanceThreshold;
		MIN_THRESHOLD.z = currDataDistance.z - iDistanceThreshold;
		
		for ( int i = 0 ; i < m_iNumExamplarFiles ; i++ )
		{
			AccelValueFileData examplar = m_Examplars.get( i );
			
			double x = GetWarpInfo( examplar.m_Angle.accelValueXs , data.m_Angle.accelValueXs );
			double y = GetWarpInfo( examplar.m_Angle.accelValueYs , data.m_Angle.accelValueYs );
			double z = GetWarpInfo( examplar.m_Angle.accelValueZs , data.m_Angle.accelValueZs );
			
			if ( m_ExamplarDB.IsKeepFrame() )
			{
				int iNumFramesOfExamplar = examplar.GetNumData();
				int iNumFramesOfCurrentData = data.GetNumData();
				
				double fFrameRate = ( double )( ( double )iNumFramesOfCurrentData / ( double )iNumFramesOfExamplar ); 
				
				x = x / fFrameRate;
				y = y / fFrameRate;
				z = z / fFrameRate;
			}
			
			double s = Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) );
			
			Axis3f d = examplar.GetDistance();
			
			h.Insert( s , currDataDistance.x - d.x , currDataDistance.y - d.y , currDataDistance.z - d.z );

			if ( fDistancce > s )
			{
				if ( iDistanceThreshold > 0 )
				{
					if ( d.x > MAX_THRESHOLD.x )
					{
						continue;
					}
					
					if ( d.x < MIN_THRESHOLD.x )
					{
						continue;
					}
	
					if ( d.y > MAX_THRESHOLD.y )
					{
						continue;
					}
	
					if ( d.y < MIN_THRESHOLD.y )
					{
						continue;
					}
	
					if ( d.z > MAX_THRESHOLD.z )
					{
						continue;
					}
	
					if ( d.z < MIN_THRESHOLD.z )
					{
						continue;
					}
				}
				
				fDistancce = s;
			}
		}
		
		return fDistancce;
	}
*/
	
	public double Compare( AccelValueFileData data , CompareHistory h , CompareResult r )
	{
		double fDistancce = Double.MAX_VALUE;
		
		for ( int i = 0 ; i < m_iNumExamplarFiles ; i++ )
		{
			AccelValueFileData examplar = m_Examplars.get( i );
			
			// 가속도
			
			double x = GetWarpInfo( examplar.m_Angle.accelValueXs , data.m_Angle.accelValueXs );
			double y = GetWarpInfo( examplar.m_Angle.accelValueYs , data.m_Angle.accelValueYs );
			double z = GetWarpInfo( examplar.m_Angle.accelValueZs , data.m_Angle.accelValueZs );
			
			if ( m_ExamplarDB.IsKeepFrame() )
			{
				int iNumFramesOfExamplar = examplar.GetNumData( AccelValueFileData.DATA_TYPE_ANGLE );
				int iNumFramesOfCurrentData = data.GetNumData( AccelValueFileData.DATA_TYPE_ANGLE );
				
				double fFrameRate = ( double )( ( double )iNumFramesOfCurrentData / ( double )iNumFramesOfExamplar ); 
				
				x = x / fFrameRate;
				y = y / fFrameRate;
				z = z / fFrameRate;
			}
			
			double a = Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) );

			// 거리
			
			x = GetWarpInfo( examplar.m_Distance.accelValueXs , data.m_Distance.accelValueXs );
			y = GetWarpInfo( examplar.m_Distance.accelValueYs , data.m_Distance.accelValueYs );
			z = GetWarpInfo( examplar.m_Distance.accelValueZs , data.m_Distance.accelValueZs );

			if ( m_ExamplarDB.IsKeepFrame() )
			{
				int iNumFramesOfExamplar = examplar.GetNumData( AccelValueFileData.DATA_TYPE_DISTANCE );
				int iNumFramesOfCurrentData = data.GetNumData( AccelValueFileData.DATA_TYPE_DISTANCE );
				
				double fFrameRate = ( double )( ( double )iNumFramesOfCurrentData / ( double )iNumFramesOfExamplar ); 
				
				x = x / fFrameRate;
				y = y / fFrameRate;
				z = z / fFrameRate;
			}
			
			double d = Math.sqrt( ( x * x ) + ( y * y ) + ( z * z ) );

			if ( fDistancce > a )
			{
				r.fAccelerate = a;
				r.fDistance = d;

				fDistancce = a;
			}
			
			h.Insert( a , d );
		}
		
		return fDistancce;
	}

	public double GetWarpInfo( ArrayList<Double> is , ArrayList<Double> js )
	{
		TimeSeries tsI = new TimeSeries( is );
		TimeSeries tsJ = new TimeSeries( js );

        try
        {
	        final DistanceFunction distFn = DistanceFunctionFactory.getDistFnByName( "EuclideanDistance" );
	        final TimeWarpInfo info = com.dtw.DTW.getWarpInfoBetween( tsI , tsJ , distFn );
	
	        return info.getDistance();
        }
        catch ( Exception e )
        {
        	return Double.MAX_VALUE;
        }
	}
}
